'''
Created on Jan 4, 2012

@author: mariano
'''
from configuration import SIZE_FOR_EASY, BUTTON_POSITION, INITIAL_POINT, OFFSET_X, OFFSET_Y
from logger import Logger
import logging
from metacog.configuration import FULLSCREEN, GREEN_TICK_FILE, RED_CROSS_FILE, \
    TUIO_ENABLE, TRIAL_TIMEOUT, MAX_PELLETS, MAX_TRIALS, \
    POINTS_PER_PELLET, POINTS_RESTART
from multineuro import game
from multineuro.sprite import ButtonSprite
from multineuro.sprite.button import Button
from psychopy import data
from score import Score
from sprite.circles import Circles
from metacog.trial import Trial
from multineuro.forms.forms import Form
from multineuro.forms.input import Input

logging.basicConfig(level=logging.DEBUG, format='%(levelname)s:\t%(message)s')


class Metacognition(game.Game):
    ''' A '''


    def _initialize(self):
        self.logger = Logger()
        self.pellets = 0
        self._initialize_circles()
        self._initialize_buttons()
        self._initialize_score()
        self._initialize_quest()
        self.initialize_form()


    def start_trials(self):
        logging.debug('Start Experiment') #Start measuring
        self.logger.start(self.log_file) #Restart trial count and mark beginning
        self.current_trial = 0
        self.trial = Trial(self.logger, self.circles, [self.button_not_know, self.button_know])
        self.add_active_sprite(self.trial.splash)
        self._show_trial()


    def process_form(self, form_result):
        self.log_file = form_result['Name'] + '.meta'
        self.start_trials()



    def initialize_form(self):
        form = Form(True)
        form.add_object('Name', Input('Nombre', '',
                                      label_size=18,
                                      input_border_color=(255, 100, 100),
                                      input_border_width=0,
                                      input_bg_color=(0, 0, 0, 0)))
        self.registerForm(form, self.process_form)

    def __init__(self):
        logging.log(logging.DEBUG, 'Welcome to Metacog')
        super(Metacognition, self).__init__("Metacognition",
                                            fullscreen=FULLSCREEN,
                                            tuio=TUIO_ENABLE)
        self._initialize()

    def _initialize_circles(self):
        """ Initialize and register circles. """
        self.circles = Circles(INITIAL_POINT, OFFSET_X, OFFSET_Y, SIZE_FOR_EASY)
        for circle in self.circles:
            self.add_active_sprite(circle)

    def _initialize_quest(self):
        """ Initialize Staircase handler used to choose hard level. """
        self.quest = data.QuestHandler(startVal=0.12,
                                       startValSd=.2,
                                       pThreshold=0.6,
                                       gamma=0.5,
                                       grain=0.005,
                                       nTrials=MAX_TRIALS,
                                       minVal=0,
                                       maxVal=0.49,
                                       stepType='lin')

    def _initialize_score(self):
        """ Initialize and register the score. """
        self.score = Score()
        self.add_background_sprite(self.score.sprite)

    def _initialize_buttons(self):
        """ Initialize and register the butttons. """
        self.button_know = Button(BUTTON_POSITION[0],
                                  self._process_trial,
                                  resource=GREEN_TICK_FILE,
                                  val=True
                                  )
        self.button_not_know = Button(BUTTON_POSITION[1],
                                      self._process_trial,
                                      resource=RED_CROSS_FILE,
                                      val=False)
        self.finnish_button = ButtonSprite('bottom-left')
        self.finnish_button.suscribe('pressed', lambda _ : self._show_prize())
        self.add_active_sprite(self.button_know)
        self.add_active_sprite(self.button_not_know)
        self.add_active_sprite(self.finnish_button)




    def _show_trial(self):
        scale = 1
        self.hard = self.current_trial % 4 != 0 #TRIAL_HARDNESS[self.current_trial]
        if self.hard:
            quest = self.quest.next()
            scale = 1 - quest
        self.trial.start(self.hard, scale, self.current_trial)


    def next_trial(self):
        """ Shows the current circles. """
        self.current_trial += 1
        self._show_trial()

    def _process_trial(self, ans):
        """ Saves the answer choosed, updates the score, and shows next 
        trial. """
        self._end_trial(self.trial.process_trial(ans))

    def _end_trial(self, trial_information):
        self.score.save_score(trial_information.score)
        self._update_quest(trial_information.correct
                           and trial_information.circle_time < TRIAL_TIMEOUT)
        if self.score.score > POINTS_PER_PELLET:
            self.pellets += 1
            self.score.restart(POINTS_RESTART)
            self._show_prize()
        else:
            self.next_trial()

    def _update_quest(self, success):
        if self.hard:
            self.quest.addData(success)

    def _show_prize(self):
        """ Hides everything and shows only the score. """
        puntaje = 'Estas en el nivel  ' + str(self.pellets + 1) + '.'
        callback = self.next_trial
        if self.pellets >= MAX_PELLETS or self.current_trial >= MAX_TRIALS:
            callback = self._show_final_score
        self.show_message(puntaje, callback=callback)

    def _show_final_score(self):
        self.show_message('Estas en el nivel ' + str(self.pellets + 1) + '.', callback=self.game_over)

    def game_over(self):
        self.logger.dump_answers()
        super(Metacognition, self).game_over()

    def close(self):
        super(self.__class__, self).close()

def main():
    """ Metacognition Game"""
    exp = None
    error = False
    try:
        exp = Metacognition()
        exp.start()
    except Exception:
        error = True
        raise
    finally:
        if error and exp:
            exp.close()


if __name__ == '__main__':
    main()
